
#include "common.h"
#include "GLXBitmapFont.h"
#include "LogUtil.h"

#include <iostream>

#include <X11/Intrinsic.h>
#include <GL/glx.h>

#include "SDL.h"


using namespace std;

__BEGIN_NAMESPACE_DECL_

GLXBitmapFont::GLXBitmapFont()
    : listBase_(0)
{
}

// Based on the glXUseXFont() example code at the OpenGL
// fontsurvey site:
//   http://www.opengl.org/resources/features/fontsurvey/
bool
GLXBitmapFont::LoadFont (const char *fontname)
{
    Display *display;
    XFontStruct *font_info;
    int first, last;    

    // Generate 256 consecutive display lists
    listBase_ = glGenLists(256);
    if (!glIsList(listBase_)) {
        ERROR << "Unable to allocate enough display lists." << endl;
        return false;
    }

    display = XOpenDisplay(0);
    if (display == 0) {
        ERROR << "XOpenDisplay() failed." << endl;
        return false;
    } 

    // Use XLoadQueryFont to load the font.
    font_info = XLoadQueryFont(display, fontname);
    if (!font_info) {
        ERROR << "XLoadQueryFont() failed." << endl;
        XCloseDisplay(display);
        return false;
    } 

    // Tell GLX which font & glyphs to use.
    first = font_info->min_char_or_byte2;
    last  = font_info->max_char_or_byte2;
    glXUseXFont (font_info->fid, first, last-first+1, listBase_+first);

    XCloseDisplay(display);

    return true;
}

int
GLXBitmapFont::Print(const char *fmt, ...) const
{
    va_list args;
    char msg[512];
    int retval;

    if (!glIsList(listBase_)) {
        ERROR << "Bad display list" << endl;
        return 0;
    }

    va_start(args, fmt);
    retval = vsnprintf (msg, 512, fmt, args);
    va_end(args);

    glPushAttrib(GL_LIST_BIT);
    glListBase(listBase_);
    glCallLists(strlen(msg), GL_UNSIGNED_BYTE, (GLubyte *)msg);
    glPopAttrib();

    return retval;
}


GLXBitmapFont::~GLXBitmapFont()
{
    if (listBase_)
        glDeleteLists(listBase_, 256);
}

__END_NAMESPACE_DECL_
